package org.swxjava.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.swxjava.CallHandler;
import org.swxjava.Container;
import org.swxjava.assembler.Compressor;
import org.swxjava.assembler.SwxAssemblerConfig;
import org.swxjava.util.Log;
import org.swxjava.util.LogFactory;
import org.swxjava.util.RequestUtils;

public class SwxGatewayServlet extends HttpServlet {

	/** SerialVersionUID */
	private static final long serialVersionUID = 1L;

	public static final String INIT_PARAM_ALLOWDOMAIN = "allowDomain";
	public static final String INIT_PARAM_COMPRESSION_LEVEL = "compressionLevel";
	
	/** Logger */
	private static final Log LOG = LogFactory.getLog(SwxGatewayServlet.class);

	private ContainerBuilder containerBuilder = null;
	private Container container = null;

	private SwxAssemblerConfig config = null;

	private CallHandler callHandler = null;

	/**
	 * 
	 */
	public SwxGatewayServlet() {
		containerBuilder = new DefaultContainerBuilder();
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doProcess(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doProcess(req, resp);
	}

	protected void doProcess(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		if (LOG.isDebugEnabled()) {
			LOG.debug("request : " + RequestUtils.createUrl(req));
		}
		container.getWebContextBuilder().set(req, res, getServletConfig(), getServletContext(), container);
		callHandler.handle(req, res);
		container.getWebContextBuilder().unset();
	}

	private CallHandler createCallHandler(SwxAssemblerConfig config) {
		DefaultCallHandler ch = new DefaultCallHandler();
		ch.getMarshaller().setSwxCompilerConfig(config);
		return ch;
	}

	@Override
	public void destroy() {
		super.destroy();
		this.config = null;
		this.container = null;
		this.callHandler = null;
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		
		initSwxAssemblerConfig(config);
		
		// create and setup a container
		container = containerBuilder.buildContainer(config);
		
		// setup a call handler
		this.callHandler = createCallHandler(this.config);

		LOG.info("SWX Gateway started.");
		LOG.info("- Allow domain is "
				+ (Boolean.parseBoolean((config.getInitParameter(INIT_PARAM_ALLOWDOMAIN))) ? "on" : "off"));
		LOG.info("- Compression level is "
				+ ((config.getInitParameter(INIT_PARAM_COMPRESSION_LEVEL) == null) ? String
						.valueOf(Compressor.DEFAULT_COMPRESSION_LEVEL) : config
						.getInitParameter(INIT_PARAM_COMPRESSION_LEVEL)));
		LOG.info("- SWX gateway is running on " + config.getServletContext().getServerInfo());
	}
	
	public void initSwxAssemblerConfig(ServletConfig sc) {
		SwxAssemblerConfig config = new SwxAssemblerConfig();
		if (sc != null) {
			// allowdomain
			String allowDomain = sc.getInitParameter(INIT_PARAM_ALLOWDOMAIN);
			config.setAllowDomain(Boolean.parseBoolean(allowDomain));
			// compression
			String compressionLevel = sc.getInitParameter(INIT_PARAM_COMPRESSION_LEVEL);
			config.setCompressionLevel(Integer.parseInt(compressionLevel == null ? String
					.valueOf(Compressor.DEFAULT_COMPRESSION_LEVEL) : compressionLevel));
		}
		this.config = config;
	}
	
	public static interface ContainerBuilder {
		Container buildContainer(ServletConfig servletConfig) throws ServletException;
	}
}
